package com.gin.supermarket_inventory_system.inventory.controller;

import com.gin.common.constant.ApiPath;
import com.gin.database.validation.EntityId;
import com.gin.database.vo.response.ResPage;
import com.gin.security.Constant.Security;
import com.gin.security.service.SystemUserInfoService;
import com.gin.spring.annotation.MyRestController;
import com.gin.spring.vo.response.Res;
import com.gin.supermarket_inventory_system.commodity.entity.CommodityPo;
import com.gin.supermarket_inventory_system.commodity.service.CommodityService;
import com.gin.supermarket_inventory_system.inventory.docket.InventoryDocket;
import com.gin.supermarket_inventory_system.inventory.dto.param.InventoryReceiptDetailPageParam;
import com.gin.supermarket_inventory_system.inventory.dto.param.InventoryReceiptPageParam;
import com.gin.supermarket_inventory_system.inventory.dto.vo.InventoryReceiptDetailVo;
import com.gin.supermarket_inventory_system.inventory.dto.vo.InventoryReceiptVo;
import com.gin.supermarket_inventory_system.inventory.entity.InventoryPo;
import com.gin.supermarket_inventory_system.inventory.entity.InventoryReceiptDetailPo;
import com.gin.supermarket_inventory_system.inventory.enums.InventoryReceiptType;
import com.gin.supermarket_inventory_system.inventory.service.InventoryReceiptDetailService;
import com.gin.supermarket_inventory_system.inventory.service.InventoryReceiptService;
import com.gin.supermarket_inventory_system.inventory.service.InventoryService;
import com.gin.supermarket_inventory_system.inventory.service.PurveyorService;
import com.gin.supermarket_inventory_system.inventory.utils.LabelValue;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * @since : 2023/9/26 16:37
 * @author : ginstone
 * @version : v1.0.0
 **/
@Slf4j
@MyRestController(InventoryReceiptGetController.API_PREFIX)
@Tag(name = InventoryReceiptGetController.GROUP_NAME)
@RequiredArgsConstructor
public class InventoryReceiptGetController {
    /**
     *  接口路径前缀
     */
    public static final String API_PREFIX = InventoryDocket.API_PREFIX + "/receipt/query";
    /**
     *  接口文档分组名称
     */
    public static final String GROUP_NAME = "库存单据查询";

    private final InventoryReceiptService receiptService;
    private final InventoryReceiptDetailService detailService;
    private final PurveyorService purveyorService;
    private final InventoryService inventoryService;
    private final CommodityService commodityService;
    private final SystemUserInfoService systemUserInfoService;

    @GetMapping(ApiPath.PAGE)
    @Operation(summary = "分页查询单据")
    @PreAuthorize(Security.PRE_AUTHORITY_URI_OR_ADMIN)
    public ResPage<InventoryReceiptVo> getPage(@ParameterObject @NotNull InventoryReceiptPageParam param,
                                               @SuppressWarnings("unused") HttpServletRequest request) {

        final ResPage<InventoryReceiptVo> pageData = receiptService.pageByParam(param, InventoryReceiptVo::new);

        // 供应商id名称映射
        final HashMap<Long, String> idNameMap = purveyorService.findIdNameMap();

        // 填充
        fillData(pageData.getData());

        return pageData;

    }

    @GetMapping("types")
    @Operation(summary = "查询所有单据类型")
    public Res<ArrayList<LabelValue>> getTypes() {
        final ArrayList<LabelValue> res = new ArrayList<>();
        for (InventoryReceiptType value : InventoryReceiptType.values()) {
            res.add(new LabelValue(value.label, value.name()));
        }
        return Res.of(res);
    }


    @GetMapping(ApiPath.GET)
    @Operation(summary = "查询单个单据", description = "包含单据详情")
    @PreAuthorize(Security.PRE_AUTHORITY_URI_OR_ADMIN)
    public Res<InventoryReceiptVo> getDetail(@RequestParam @EntityId(service = InventoryReceiptService.class) @Parameter(description = "id") long id,
                                             @SuppressWarnings("unused") HttpServletRequest request) {
        final InventoryReceiptVo vo = new InventoryReceiptVo(receiptService.getById(id));

        fillData(Collections.singleton(vo));


        // 填充查询单据详情
        final List<InventoryReceiptDetailPo> details = detailService.listByReceiptId(vo.getId());
        if (!details.isEmpty()) {
            final List<InventoryReceiptDetailVo> data = details.stream().map(InventoryReceiptDetailVo::new).toList();
            // 库存信息
            final List<InventoryPo> inventories = inventoryService.listByIds(data.stream().map(InventoryReceiptDetailVo::getInventoryId).collect(Collectors.toSet()));
            // 商品信息
            final List<CommodityPo> commodities = commodityService.listByIds(inventories.stream().map(InventoryPo::getCommodityId).collect(Collectors.toSet()));

            // 填充数据
            data.forEach(detail ->
                    //查找匹配的库存和商品信息
                    inventories.stream()
                            .filter(i -> i.getId() == detail.getInventoryId())
                            .findFirst()
                            .ifPresent(inventory -> commodities.stream()
                                    .filter(i -> Objects.equals(i.getId(), inventory.getCommodityId()))
                                    .findFirst()
                                    .ifPresent(commodity -> {
                                        // 填充数据

                                        // 条码
                                        detail.setBarcode(inventory.getBarcode());
                                        // 规格
                                        detail.setSpec(inventory.getSpec());
                                        // 全名
                                        detail.setName(String.format("%s %s", commodity.getName(), inventory.getName()));
                                    })));

            vo.setDetails(data);
        }
        return Res.of(vo);
    }


    @GetMapping("detail")
    @Operation(summary = "按库存查询单据详情")
    @PreAuthorize(Security.PRE_AUTHORITY_URI_OR_ADMIN)
    public ResPage<InventoryReceiptDetailVo> getPage(@ParameterObject @NotNull InventoryReceiptDetailPageParam param,
                                                     @SuppressWarnings("unused") HttpServletRequest request) {
        return detailService.pageByParam(param, InventoryReceiptDetailVo::new);
    }

    private void fillData(Collection<InventoryReceiptVo> receipts) {
        // 供应商id名称映射
        final HashMap<Long, String> idNameMap = purveyorService.findIdNameMap();

        final HashMap<Long, String> userIdNameMap = systemUserInfoService.getIdNameMap(receipts.stream().map(InventoryReceiptVo::getUserId).collect(Collectors.toSet()));

        for (InventoryReceiptVo receipt : receipts) {
            // 供应商名称
            receipt.setPurveyorName(idNameMap.get(receipt.getPurveyorId()));
            // 操作人名称
            receipt.setUsername(userIdNameMap.get(receipt.getUserId()));
        }

    }
}